package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.BrandDTO;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entiey.*;
import com.leyou.item.mapper.SkuMapper;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import static com.leyou.common.constants.MQConstants.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {

    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SpuDetailService spuDetailService;
    @Autowired
    private SkuService skuService;

    @Resource
    private SpuMapper spuMapper;
    @Resource
    private SkuMapper skuMapper;

    @Autowired
    private AmqpTemplate amqpTemplate;


    //分页查询商品
    @Override
    public PageDTO<SpuDTO> querySpuByPage(Long brandId, Long categoryId,
                                          Long id, Long page, Long rows, Boolean saleable) {

        //分页健壮性处理
        long pageSize = Math.max(1, page);
        long pageRows = Math.min(5,rows);

        //拼接分页查询条件
        //select * from tb_spu  where id = '3' and brand_id= '15127' and saleable = '1' and cid3 = '76'
        //limit 0,2
        Page<Spu> pageInfo = query().eq(id!=null,"id", id).eq(brandId !=null,"brand_id", brandId)
                .eq(saleable !=null,"saleable", saleable).eq(categoryId != null,"cid3", categoryId)
                .page(new Page<>(pageSize, pageRows));
        //page<Spu> 转换为page<SpuDto>
        List<Spu> spuList = pageInfo.getRecords();
        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(spuList);
        //遍历查询品牌名称和类别名称   赋值给spuDTO
        for (SpuDTO spuDTO : spuDTOList) {
            queryBrandAndCategory(spuDTO);
        }

        return new PageDTO<>(pageInfo.getTotal(),pageInfo.getPages(),spuDTOList);
    }


    private void queryBrandAndCategory(SpuDTO spuDTO) {
        //1.赋值分类名称
        //1.1 获取多级分类集合  调用DTO中get方法
        List<Long> categoryIds = spuDTO.getCategoryIds();
        //1.2 查询Category表获得表信息信息
        List<Category> categories = categoryService.listByIds(categoryIds);
        //1.3 判断对应的种类是否存在
        if (!StringUtils.isEmpty(categories)){
            String categoryName = categories.stream().map(Category::getName).collect(Collectors.joining("/"));
            spuDTO.setCategoryName(categoryName);
        }

        //2.赋值品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand!=null){
            spuDTO.setBrandName(brand.getName());
        }
    }

    /**
     * 涉及三个表  tb_spu  tb_spuDetail  tb_sku
     * @param spuDTO
     */
    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {

        //1 添加tb_spu表
        //1.1 将dto转换为pojo类型
        Spu spu = spuDTO.toEntity(Spu.class);
        //1.2 是否上架默认选择false
        spu.setSaleable(false);
        boolean success = this.save(spu);

        if (!success){
            throw new LyException(500,"商品添加失败！");
        }

        //2 添加tb_spuDetail表
        //获取SpuDetail  转化为pojo
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        //tb_spuDetail表Id 取值为tb_spu表的id
        spuDetail.setSpuId(spu.getId());
        success = spuDetailService.save(spuDetail);
        if (!success){
            throw new LyException(500,"添加商品详情失败！");
        }

        //3 添加tb_sku表
        //3.1 获取skus
        List<SkuDTO> skus = spuDTO.getSkus();
        //3.2 新建集合 存放Sku
        ArrayList<Sku> list = new ArrayList<>(skus.size());
        //3.3遍历取出  转为pojo对象后 将特殊值进行赋值后，添加到集合中
        for (SkuDTO skuDTO : skus) {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSpuId(spu.getId());
            sku.setSaleable(false);
            list.add(sku);
        }
        //批量插入数据
        success = skuService.saveBatch(list);

        if (!success){
            throw new LyException(500,"添加商品特有属性失败！");
        }


    }

    //商品上下架
    @Override
    @Transactional
    public void updateSaleableById(Long id, Boolean saleable) {
        //更新spu
        Boolean success = spuMapper.goodsIsSaleable(id,saleable);
        if (!success) throw new LyException(500,"更新失败！");
        //对应的sku也需要下架处理
        success = skuMapper.goodsIsSaleable(id,saleable);
        if (!success) throw new LyException(500,"更新失败！");

//        success =skuService.update().eq("spu_id", id).set("saleable", saleable).update();
//        if (!success) {
//            throw new LyException(500, "更新失败");
//        }

        // 3.发送MQ消息
        String routingKey = saleable ? RoutingKeyConstants.ITEM_UP_KEY : RoutingKeyConstants.ITEM_DOWN_KEY;
        amqpTemplate.convertAndSend(ExchangeConstants.ITEM_EXCHANGE_NAME, routingKey, id);

    }

//    根据id查询spu及sku、spuDetail等
    @Override
    public SpuDTO querySpuAndSkuAndSpuDetailById(Long id) {
        //查询spu
        Spu spu = this.getById(id);
        if (spu == null) throw new LyException(400,"商品不存在!");

        //查询sku
        List<Sku> skuList = skuService.query().eq("spu_id", id).list();
        if (skuList == null) throw new LyException(400,"商品不存在!");

        //查询spuDetail
        SpuDetail spuDetail = spuDetailService.getById(id);
        if (spuDetail == null) throw new LyException(400,"商品不存在!");

        //将pojo转化为dto对象
        SpuDTO spuDTO = new SpuDTO(spu);
        //将结果注入SpuDTO对象中
        spuDTO.setSkus(SkuDTO.convertEntityList(skuList));
        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));

        //查询品牌名称 类别名称
        queryBrandAndCategory(spuDTO);

        return spuDTO;
    }

    //更改商品信息
    @Override
    @Transactional
    public void updateGoods(SpuDTO spuDTO) {
        //1.判断是否修改tb_spu信息
        if (spuDTO.getId()!=null){
            //1.1 将dto对象转换为pojo类型
            Spu spu = spuDTO.toEntity(Spu.class);
            //1.2 是否上架  将值设为空
            spu.setSaleable(null);
            //1.3 执行修改方法
            boolean success = this.updateById(spu);
            if (!success) throw new LyException(500,"修改商品信息失败！");
        }
        //2. 判断是否修改tb_spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (spuDetailDTO!=null&&spuDetailDTO.getSpuId()!=null){
            //2.1转化为pojo对象 修改信息
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            //2.2 修改tb_spuDetail
            boolean success = spuDetailService.updateById(spuDetail);
            if (!success) throw new LyException(500,"修改商品信息失败！");
        }
        //3.判断是否修改tb_sku
        List<SkuDTO> skus = spuDTO.getSkus();
        if(CollectionUtils.isEmpty(skus)){
            return;
        }
        //3.1 获取商品详情信息  转化成pojo对象
/*        List<Sku> skuList = skus.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class)).collect(Collectors.toList());
        for (Sku sku : skuList) {
            //判断是否存在saleable字段  没有则执行删除  存在则增或改
            if (sku.getSaleable()==null){
                skuService.removeById(sku.getId());
            }else {
                skuService.saveOrUpdate(sku);
            }
        }*/
        //优化
        Map<Boolean, List<Sku>> skuListBySaleable = skus.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

        //获取要删除的sku
        List<Sku> skuListFalse = skuListBySaleable.get(false);
        if (!CollectionUtils.isEmpty(skuListFalse)){
            //收集需要删除的信息
            List<Long> skuIdList = skuListFalse.stream().map(Sku::getId).collect(Collectors.toList());
            //批量删除
            skuService.removeByIds(skuIdList);
        }

        //获取要新增或修改的sku
        List<Sku> skuListTrue = skuListBySaleable.get(true);
        if (!CollectionUtils.isEmpty(skuListTrue)){
            //批量添加
            skuService.saveOrUpdateBatch(skuListTrue);
        }
    }
}